package fields;

import static fields.Util.*;
import static fields.DrawerType.*;

import java.awt.*;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

public class Drawer {
    private Point2D startPoint;
    private final DrawerType type;

    public Drawer(Point2D startPoint, DrawerType type) {
        this.startPoint = startPoint;
        this.type = type;
    }

    public Point2D getStartPoint() {
        return startPoint;
    }

    public void setStartPoint(Point2D startPoint) {
        this.startPoint = startPoint;
    }

    public DrawerType getType() {
        return type;
    }

    public List<PowerPoint> getDraw(List<Charge> charges, Rectangle bounds) {
        Point2D.Double p = new Point2D.Double(startPoint.getX(), startPoint.getY());
        List<PowerPoint> draw = new ArrayList<PowerPoint>();
        Point2D.Double old;
        Point2D.Double prev;
        Point2D.Double first;
        Point2D.Double second;
        common:
        for (int i = 0; i < MAX_DRAW_COUNT; i++) {
            if (Double.isNaN(p.getX()) || Double.isNaN(p.getY()))
                break;
            double[] f = new double[2];
            for (Charge charge : charges) {
                double[] ff = charge.getF(p);
                f[0] += ff[0];
                f[1] += ff[1];

            }

            double power = norm(f);
            for (Charge charge : charges) {
                if (p.distance(charge.getPoint()) < 1) {
                    draw.add(new PowerPoint(p, power));
                    break common;
                }
            }
            if (!bounds.contains(p) || i == MAX_DRAW_COUNT - 1) {
                draw.add(new PowerPoint(p, power));
                break;
            }
            if (draw.size() > 2) {
                prev = draw.get(draw.size() - 1);
                if (prev.distanceSq(p) > MAX_DRAW_SECTION_SQ_LENGTH) {
                    draw.add(new PowerPoint(p, power));
                } else {
                    old = draw.get(draw.size() - 2);
                    first = new Point2D.Double(prev.getX() - old.getX(), prev.getY() - old.getY());
                    second = new Point2D.Double(p.getX() - prev.getX(), p.getY() - prev.getY());
//                norm(first);
//                norm(second);
                    double crossProduct = first.getX() * second.getY() - first.getY() * second.getX();
                    if (Math.abs(crossProduct) >/*.02*/.3)
                        draw.add(new PowerPoint(p, power));
                }
            } else {
                draw.add(new PowerPoint(p, power));
            }

            if (type == FORCE_INC)
                p = new Point2D.Double(p.getX() + f[0], p.getY() + f[1]);
            else if (type == FORCE_DEC)
                p = new Point2D.Double(p.getX() - f[0], p.getY() - f[1]);
            else if (type == FORCE_LEFT)
                p = new Point2D.Double(p.getX() - f[1], p.getY() + f[0]);
            else if (type == FORCE_RIGHT)
                p = new Point2D.Double(p.getX() + f[1], p.getY() - f[0]);
        }
        return draw;
    }
}
